package com.atty.dms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.atty.dms.common.biz.user.UserContext;
import com.atty.dms.common.convention.exception.ClientException;
import com.atty.dms.common.enums.UserErrorCodeEnum;
import com.atty.dms.dao.entity.UserDO;
import com.atty.dms.dao.mapper.UserMapper;
import com.atty.dms.dto.req.UserLoginReqDTO;
import com.atty.dms.dto.req.UserRegisterReqDTO;
import com.atty.dms.dto.req.UserUpdateReqDTO;
import com.atty.dms.dto.resp.UserLoginRespDTO;
import com.atty.dms.dto.resp.UserRespDTO;
import com.atty.dms.service.UserService;
import com.atty.dms.tools.DesensitizationUtils;
import com.atty.dms.tools.JwtUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.atty.dms.common.enums.UserErrorCodeEnum.USER_EXIST;
import static com.atty.dms.common.enums.UserErrorCodeEnum.USER_NAME_EXIST;

/**
 * ClassName:UserServiceImpl
 * Package:com.atty.dms.service.impl
 * Description:
 *
 * @Author:tony
 * @Create :2025/4/13 10:30
 * @Version :1.0
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {

    private final JwtUtil jwtUtil;
    private final UserMapper userMapper;

    @Override
    public UserRespDTO getUserByUsername(String username) {
        LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
                .eq(UserDO::getUsername, username);
        UserDO userDo = baseMapper.selectOne(queryWrapper);
        if (userDo == null) {
            throw new ClientException(UserErrorCodeEnum.USER_NULL);
        }
        UserRespDTO result = new UserRespDTO();
        BeanUtils.copyProperties(userDo, result);
        return result;
    }

    @Override
    public UserRespDTO getUserByUserId(Long userId) {
        LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
                .eq(UserDO::getUserId, userId);
        UserDO userDO = baseMapper.selectOne(queryWrapper);
        if (userDO == null) {
            throw new ClientException("用户不存在");
        }
        return BeanUtil.toBean(userDO, UserRespDTO.class);
    }

    @Override
    public boolean hasUsername(String username) {
        LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
                .eq(UserDO::getUsername, username);
        UserDO userDO = baseMapper.selectOne(queryWrapper);
        return userDO != null;
    }

    @Override
    public void register(UserRegisterReqDTO requestParam) {
        // 检查用户名是否可用
        if (hasUsername(requestParam.getUsername())) {
            throw new ClientException(USER_NAME_EXIST);
        }
        try {
            int insert = baseMapper.insert(BeanUtil.toBean(requestParam, UserDO.class));
            if (insert < 1) {
                throw new ClientException(UserErrorCodeEnum.USER_SAVE_ERROR);
            }
        } catch (DuplicateKeyException ex) {
            // 数据库层唯一约束冲突
            throw new ClientException(USER_EXIST);
        }
    }

    @Override
    public int update(UserUpdateReqDTO requestParam) {
        if(requestParam.getRole()!=3){
            if(!Objects.equals(requestParam.getUsername(), UserContext.getUsername())){
                throw new ClientException("当前登录用户信息异常");
            }
        }
        LambdaUpdateWrapper<UserDO> updateWrapper = Wrappers.lambdaUpdate(UserDO.class)
                .eq(UserDO::getUsername, requestParam.getUsername());
        return baseMapper.update(BeanUtil.toBean(requestParam, UserDO.class), updateWrapper);
    }

    @Override
    public UserLoginRespDTO login(UserLoginReqDTO requestParam) {
        LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
                .eq(UserDO::getUsername, requestParam.getUsername())
                .eq(UserDO::getPassword, requestParam.getPassword());
        UserDO userDO = baseMapper.selectOne(queryWrapper);
        if (userDO == null) {
            throw new ClientException("用户不存在或密码错误");
        }
        //后续可加入缓存
        // 生成JWT
        String accessToken = jwtUtil.generateToken(userDO.getUsername(), userDO.getUserId());
        UserLoginRespDTO userLoginRespDTO = new UserLoginRespDTO();
        userLoginRespDTO.setUsername(userDO.getUsername());
        userLoginRespDTO.setAccessToken("Bearer "+accessToken);
        userLoginRespDTO.setExpiresIn(jwtUtil.getExpiration()); // 需要添加getter方法
        userLoginRespDTO.setRole(userDO.getRole());
        return userLoginRespDTO;
    }

    @Override
    public Boolean checkLogin(String username, String token) {
        if(!Objects.equals(username, UserContext.getUsername())){
            throw new ClientException("用户未登录或会话已过期");
        }
        // 在通过用户上下文校验后是否需要查询数据库（可选）
//        if(!hasUsername(username)){
//            throw new ClientException("该用户尚未注册");
//        }
        return true;
    }

    @Override
    public void logout(String username, String token) {
        // 去掉前缀 "Bearer "（假设前端传入的 Token 包含前缀）
        token = token.substring(7);
        // 检查用户是否已登录
        if (!checkLogin(username, token)) {
            throw new ClientException("用户未登录或会话已过期");
        }
        // 注销 Token
        jwtUtil.invalidateToken(token);
    }

    @Override
    public Page<UserRespDTO> getAllUsersByPage(int pageNum, int pageSize) {
        checkAdminPermission();

        try {
            // 构建分页查询条件
            Page<UserDO> userPage = new Page<>(pageNum, pageSize);
            Page<UserDO> resultPage = baseMapper.selectPage(userPage, null);

            // 转换为响应对象并脱敏
            List<UserRespDTO> userRespDTOList = resultPage.getRecords().stream()
                    .map(userDO -> {
                        UserRespDTO respDTO = BeanUtil.toBean(userDO, UserRespDTO.class);
                        // 对敏感信息进行脱敏处理
                        respDTO.setEmail(DesensitizationUtils.desensitizeEmail(respDTO.getEmail()));
                        respDTO.setPhone(DesensitizationUtils.desensitizePhone(respDTO.getPhone()));
                        return respDTO;
                    })
                    .collect(Collectors.toList());

            // 创建新的 Page<UserRespDTO> 对象
            Page<UserRespDTO> pageResult = new Page<>();
            pageResult.setCurrent(resultPage.getCurrent()); // 当前页码
            pageResult.setSize(resultPage.getSize());       // 每页大小
            pageResult.setTotal(resultPage.getTotal());     // 总记录数
            pageResult.setRecords(userRespDTOList);         // 设置转换后的记录

            return pageResult;
        }catch (Exception e){
            log.error("获取用户列表失败", e);
            throw new ClientException("获取用户列表失败");
        }
    }

    /**
     * 检查管理员权限
     */
    private void checkAdminPermission() {
        String userId = UserContext.getUserId();
        LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
                .eq(UserDO::getUserId, userId);
        UserDO userDO = baseMapper.selectOne(queryWrapper);

        if (userDO == null || userDO.getRole() != 1) {
            throw new ClientException("当前用户无权访问");
        }
    }



    public List<UserDO> getUsersByIds(List<Long> studentIds) {
        if (studentIds == null || studentIds.isEmpty()) {
            return List.of(); // 返回空列表
        }

        QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id", studentIds); // 假设user表中的主键字段名为user_id
        return userMapper.selectList(queryWrapper);
    }

    @Override
    public Page<UserRespDTO> getAllUsersByGenderAndNotInDormitoryByPage(int pageNum, int pageSize, Integer gender) {
        // 构建分页查询条件
        Page<UserDO> userPage = new Page<>(pageNum, pageSize);

        // 创建查询条件
        QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("gender", gender)
                .eq("has_dormitory", 0) // 假设 has_dormitory 字段标识用户是否有宿舍
                .eq("role", 3);         // 过滤特定角色

        // 执行查询
        Page<UserDO> resultPage = baseMapper.selectPage(userPage, queryWrapper);

        // 转换为响应对象并脱敏
        List<UserRespDTO> userRespDTOList = resultPage.getRecords().stream()
                .map(userDO -> {
                    UserRespDTO respDTO = BeanUtil.toBean(userDO, UserRespDTO.class);
                    // 对敏感信息进行脱敏处理
                    respDTO.setEmail(DesensitizationUtils.desensitizeEmail(respDTO.getEmail()));
                    respDTO.setPhone(DesensitizationUtils.desensitizePhone(respDTO.getPhone()));
                    return respDTO;
                })
                .collect(Collectors.toList());

        // 创建新的 Page<UserRespDTO> 对象
        Page<UserRespDTO> pageResult = new Page<>();
        pageResult.setCurrent(resultPage.getCurrent()); // 当前页码
        pageResult.setSize(resultPage.getSize());       // 每页大小
        pageResult.setTotal(resultPage.getTotal());     // 总记录数
        pageResult.setRecords(userRespDTOList);         // 设置转换后的记录

        return pageResult;
    }


}
